package com.fingard.dsp.bank.directbank.jsjnrcb02;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directConfig.FtpSet;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.ReqQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.RetAtsQryBatPayRec;
import com.fingard.dsp.bank.reqrespobj.batpayrec.detail.RetAtsBatPayRecDetail;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.SftpPortClient;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.BufferedReader;
import java.io.File;
import java.io.StringReader;
import java.text.MessageFormat;
import java.util.Date;

/**
 * JSJNRCB02-江南农商行代收付系统
 */
public class JSJNRCB02BatPayRec extends JSJNRCB02Base implements IBatPayRec {
    @Override
    public RetAtsBatPayRec d_1988_BatPay(ReqBatPayRec p_req1988) throws Exception {
        return d_BatPayRec(p_req1988);
    }

    @Override
    public RetAtsQryBatPayRec d_1998_QryBatPay(ReqQryBatPayRec p_req1998) throws Exception {
        return d_QryBatPayRec(p_req1998);
    }

    @Override
    public RetAtsBatPayRec d_9188_BatPay(ReqBatPayRec p_req9188) throws Exception {
        return d_BatPayRec(p_req9188);
    }

    @Override
    public RetAtsQryBatPayRec d_9198_QryBatPay(ReqQryBatPayRec p_req9198) throws Exception {
        return d_QryBatPayRec(p_req9198);
    }

    /**
     * 批量代收付提交
     *
     * @param p_reqBat 批量代收付请求对象
     * @return 批量代收付响应对象
     * @throws Exception
     */
    public RetAtsBatPayRec d_BatPayRec(ReqBatPayRec p_reqBat) throws Exception {
        RetAtsBatPayRec retAts = new RetAtsBatPayRec(p_reqBat.reqHeader);
        retAts.reqSeqID = p_reqBat.reqBatchNO;

        try {
            ActSetItem actItem = this.getBankConfig().getActSetItem(p_reqBat.ownAct, "bat");
            if (actItem == null) {
                retAts.respCode = "0";
                retAts.respInfo = "未找到账号:[" + p_reqBat.ownAct + "]商户配置信息!";
                retAts.reqSeqID = p_reqBat.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }

            // 代收付文件内容
            StringBuilder sbFileContent = new StringBuilder();

            // 汇总信息：总笔数|文件总金额(单位:分)|借贷标志\n
            String cdFlag = "1";
            if (p_reqBat.reqHeader.isBatRec) {
                cdFlag = "2";
            }
            String tmpReqHeader = MessageFormat.format("{0}|{1}|{2}", p_reqBat.totalNum, StringHelper.amountMultiply100(p_reqBat.totalAmt), cdFlag);
            sbFileContent.append(tmpReqHeader);

            // 文件明细
            while (p_reqBat.readRecord()) {
                if (sbFileContent.length() > 0) {
                    sbFileContent.append("\n");
                }

                String postScript = p_reqBat.readedDetail.askNumber;
                String payAmt = StringHelper.amountMultiply100(p_reqBat.readedDetail.payAmount);

                String summary = "";
                String oppAct = "";
                String oppName = "";
                if (p_reqBat.reqHeader.isBatPay) {
                    summary = "代付";
                    oppAct = p_reqBat.readedDetail.recAct;
                    oppName = p_reqBat.readedDetail.recName;
                } else {
                    oppAct = p_reqBat.readedDetail.payAct;
                    oppName = p_reqBat.readedDetail.payName;
                    summary = "代扣";
                }

                // 明细信息:序列号(20位)|客户账号|客户账号户名|交易金额(单位:分)|借贷标志(1借,2贷)|摘要\n
                String tmpReqBodyDetail = MessageFormat.format("{0}|{1}|{2}|{3}|{4}|{5}", postScript, oppAct, oppName, payAmt, cdFlag, summary);
                sbFileContent.append(tmpReqBodyDetail);
            }
            WriteBankLogLn2("批次提交文件内容:\r\n" + sbFileContent.toString());

            // 上传文件保存本地: ENY(3位)+IAAS(4位)+保险公司代码（3位）+地区号(5位)+网点号(5位)+代理业务编号(9位)+ YYYYMMDD(日期8位)+ AGENT(5位)+批次(10位)+ATS.txt
            String tmpPaySendDate = Format.Date8Format.format(p_reqBat.getPayDateTime());

            String busCode = "000200001";
            if (p_reqBat.reqHeader.isBatPay) {
                busCode = "000200002";
            }

            String tmpUploadFileName = "ENYIAAS" + bankFront.corpNo + actItem.areaCode + actItem.cnapsCode + busCode + tmpPaySendDate + "AGENT" + p_reqBat.reqBatchNO + ".txt";
            String tmpLocalMarkPath = getTempFileDirectory() + File.separator + tmpUploadFileName;
            WriteBankLogLn2("批次文件保存本机路径: " + tmpLocalMarkPath);

            if (FileHelper.existFile(tmpLocalMarkPath)) {
                retAts.respCode = "0";
                retAts.respInfo = "本地批次文件已上传,请勿重复上传!";
                retAts.reqSeqID = p_reqBat.reqBatchNO;
                retAts.transState = PaymentState.FAIL_Batch;
                retAts.payInfoCode = FailCode.E9981;
                retAts.writeRetToATS();
                return retAts;
            }

            FileHelper.writeFile(tmpLocalMarkPath, sbFileContent.toString(), getCharset());

            // 上送FTP服务器
            FtpSet ftpSet = bankFront.getFtpSet("bat-upload");
            FtpReceiver ftpReceiver = null;
            String requestType = getBankConfig().getSetValue("requestType","FTP","upload");
            if (requestType != null && "SFTP".equalsIgnoreCase(requestType)) {
                SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
                String sftpFilePath = StringHelper.trimEnd(ftpSet.upDir, "/") + "/" + tmpUploadFileName;
                ftpReceiver = sftpPortClient.uploadFile("", tmpLocalMarkPath, sftpFilePath);
                sftpPortClient.disconnect();
            } else {
                FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
                ftpReceiver = ftpPortClient.uploadFile(tmpLocalMarkPath, tmpUploadFileName);
                ftpPortClient.disconnect();
            }

            retAts.respCode = "0";
            if (!ftpReceiver.isCompleted) {
                retAts.respCode = "-1";
                retAts.respInfo = ftpReceiver.connMsg;
            } else if (ConnState.FAIL.equals(ftpReceiver.connState)) {
                retAts.respInfo = "上传失败!";
                retAts.transState = "BatchFailed";
                retAts.payInfoCode = "E9999";
            } else {
                WriteBankLogLn("文件上传成功,开始发送通知报文:\r\n");
                XmlTextWriter xmlWriter = new XmlTextWriter();
                xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"GBK\"?>");
                xmlWriter.writeStartElement("root");
                xmlWriter.writeStartElement("head");
                xmlWriter.writeElementString("transcode", "B0004");
                Date tmpDateNow = new Date();
                xmlWriter.writeElementString("transdate", Format.Date8Format.format(tmpDateNow));
                xmlWriter.writeElementString("transtime", Format.Time6Format.format(tmpDateNow));
                xmlWriter.writeEndElement();
                xmlWriter.writeStartElement("body");
                xmlWriter.writeElementString("thirdserialno", p_reqBat.reqBatchNO);
                xmlWriter.writeElementString("sysid", bankFront.org);
                xmlWriter.writeElementString("thdaskfilename", tmpUploadFileName);
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        retAts.respCode = "0";
                        retAts.respInfo = tmpBkReader.getFirstText("/root/body/dealmsg");
                        retAts.transState = tmpBkReader.getFirstText("/root/body/dealcode");
                        retAts.payInfoCode = tmpBkReader.getFirstText("/root/body/dealcode");
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = tmpStrRet[1];
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetToATS();
        return retAts;
    }

    /**
     * 批量代收付状态查询
     *
     * @param p_reqQryBat
     * @return
     * @throws Exception
     */
    public RetAtsQryBatPayRec d_QryBatPayRec(ReqQryBatPayRec p_reqQryBat) throws Exception {
        RetAtsQryBatPayRec retAts = new RetAtsQryBatPayRec(p_reqQryBat.reqHeader);
        retAts.reqSeqID = p_reqQryBat.reqBatchNO;

        try {
            ActSetItem actItem = this.getBankConfig().getActSetItem(p_reqQryBat.ownAct, "bat");
            if (actItem == null) {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号:[" + p_reqQryBat.ownAct + "]商户配置信息!";
                retAts.writeAfterDetail();
                return retAts;
            }

            // 下载文件名命名规则:ENY+保险公司代码+01+地区号+网点号+代理业务编号+YYYYMMDD+BATCHRET+批次+ATS.txt
            String tmpPaySendDate = Format.Date8Format.format(p_reqQryBat.getBgnDateTime());

            String busCode = "000200001";
            if (p_reqQryBat.reqHeader.isBatPay) {
                busCode = "000200002";
            }

            String tmpDownFileName = "ENY" + bankFront.corpNo + "01" + actItem.areaCode + actItem.cnapsCode + busCode + tmpPaySendDate + "BATCHRET" + p_reqQryBat.reqBatchNO + ".txt";
            String tmpLocalMarkPath = createTempFileDirectory() + File.separator + tmpDownFileName;
            WriteBankLogLn2("批次结果文件保存本地路径: " + tmpLocalMarkPath);

            FtpSet ftpSet = bankFront.getFtpSet("bat-download");
            FtpReceiver ftpReceiver = null;
            String requestType = getBankConfig().getSetValue("requestType","FTP", "download");
            if (requestType != null && "SFTP".equalsIgnoreCase(requestType)) {
                String sftpFilePath = StringHelper.trimEnd(ftpSet.downDir, "/") + "/" + tmpDownFileName;
                WriteBankLogLn2("待下载SFTP服务器文件路径:\r\n" + sftpFilePath);
                SftpPortClient sftpPortClient = new SftpPortClient(ftpSet);
                ftpReceiver = sftpPortClient.downloadFile("", sftpFilePath, tmpLocalMarkPath);
                sftpPortClient.disconnect();
            } else {
                FtpPortClient ftpPortClient = new FtpPortClient(ftpSet);
                ftpReceiver = ftpPortClient.downloadFile(tmpDownFileName, tmpLocalMarkPath);
                ftpPortClient.disconnect();
            }

            if (ftpReceiver.isCompleted) {
                WriteBankLogLn("结果文件下载成功,开始解析...");
                String tmpStrRet = FileHelper.readFileText(tmpLocalMarkPath, getCharset());
                WriteBankLogLn2("本地批次结果文件内容:\r\n" + tmpStrRet);

                if (StringHelper.hasAnyChar(tmpStrRet)) {
                    retAts.respCode = "0";

                    // 整批失败
                    String[] tmpHeadArray = tmpStrRet.split("\n");
                    if ((tmpHeadArray != null) && (tmpHeadArray.length == 2) && ("2000".equals(tmpHeadArray[1].split("\\|")[5]) || "3000".equals(tmpHeadArray[1].split("\\|")[5]))) {
                        String[] errArray = tmpHeadArray[1].split("\\|");
                        retAts.transState = errArray[5];
                        retAts.payInfoCode = errArray[5];
                        retAts.respInfo = errArray[6];
                        retAts.writeAfterDetail();
                        return retAts;
                    }

                    StringReader strReader = new StringReader(tmpStrRet);
                    BufferedReader tmpReader = new BufferedReader(strReader);
                    tmpReader.readLine();

                    while(true) {
                        String eachline = tmpReader.readLine();
                        if(StringHelper.isNullOrEmpty(eachline)){
                            break;
                        }
                        if (eachline.indexOf("|") > 0) {
                            // 明细记录:序列号|客户账号|交易金额(单位:分)|借贷标志|摘要|错误代码|失败原因\n
                            String[] bodyValues = eachline.split("\\|");
                            RetAtsBatPayRecDetail tmpRetDetail = new RetAtsBatPayRecDetail();

                            if(p_reqQryBat.reqHeader.transType.equals("1998")){
                                tmpRetDetail.recAct = bodyValues[1];
                                tmpRetDetail.recName = bodyValues[2];
                            } else if(p_reqQryBat.reqHeader.transType.equals("9198")){
                                tmpRetDetail.payAct = bodyValues[1];
                                tmpRetDetail.payName = bodyValues[2];
                            }

                            tmpRetDetail.postScript = bodyValues[0];
                            tmpRetDetail.payAmount = StringHelper.amountDivide100(bodyValues[3]);
                            tmpRetDetail.result = bodyValues[6];
                            tmpRetDetail.payInfoCode = bodyValues[6];
                            tmpRetDetail.memo = bodyValues[7];

                            retAts.writeRetDetail(tmpRetDetail);
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = "银行返回明细数据格式非法!";
                        }
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "本地批次结果文件内容为空!";
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "批次结果文件下载失败:" + ftpReceiver.connMsg;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeAfterDetail();
        return retAts;
    }
}